package org.hackystat.storageservice.resources.alt;

import org.hackystat.utilities.stacktrace.StackTrace;
import org.restlet.data.CharacterSet;
import org.restlet.data.Language;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.resource.StringRepresentation;

/**
 *
 * Created by IntelliJ IDEA.
 * User: STE2112
 * Date: 05-05-2011
 * Time: 09:38:14
 * To change this template use File | Settings | File Templates.
 */
public class Util {
    private Request request;
    private Response response;

    public Util(Request request, Response response) {
        this.request = request;
        this.response = response;
    }

    /**
     * Called when an exception is caught while processing a request.
     * Just sets the response code.
     *
     * @param timestamp The timestamp that could not be parsed.
     */
    public void setStatusBadTimestamp(String timestamp) {
        response.setStatus(Status.SERVER_ERROR_INTERNAL, removeNewLines(badTimestamp(timestamp)));
    }


    /**
     * Called when an exception is caught while processing a request.
     * Just sets the response code.
     *
     * @param e The exception that was caught.
     */
    public void setStatusInternalError(Exception e) {
        response.setStatus(Status.SERVER_ERROR_INTERNAL, removeNewLines(internalError(e)));
    }

    /**
     * Called when a miscellaneous "one off" error is caught during processing.
     *
     * @param msg A description of the error.
     */
    public void setStatusMiscError(String msg) {
        response.setStatus(Status.CLIENT_ERROR_BAD_REQUEST, removeNewLines(miscError(msg)));
    }

    /**
     * The error message for requests that only the admin can handle.
     *
     * @return A string describing the problem.
     */
    public String adminOnly() {
        return String.format("Request requires administrator privileges:%n  Request: %s %s",
                request.getMethod().getName(),
                request.getResourceRef().toString());
    }

    /**
     * The error message for requests where the authorized user must be the same as the user
     * in the URI string, or the authorized use is the admin (and then the user in the URI string
     * can be anyone).
     *
     * @param authUser The authorized user.
     * @param uriUser  The user in the URI string.
     * @return A string describing the problem.
     */
    public String adminOrAuthUserOnly(String authUser, String uriUser) {
        return String.format("Request requires authorized user (%s) to be the same user as the " +
                "URL user (%s):%n  Request: %s %s", authUser, uriUser,
                request.getMethod().getName(),
                request.getResourceRef().toString());
    }

    /**
     * The error message for requests that generate an unspecified internal error.
     *
     * @param e The exception.
     * @return A string describing the problem.
     */
    public String internalError(Exception e) {
        String message = String.format("Internal error %s:%n  Request: %s %s",
                e.getMessage(),
                request.getMethod().getName(),
                request.getResourceRef().toString());
        System.out.println(String.format("%s\n%s", message, StackTrace.toString(e)));
        return message;
    }

    /**
     * The error message for miscellaneous "one off" error messages.
     *
     * @param message A short string describing the problem.
     * @return A string describing the problem.
     */
    public String miscError(String message) {
        return String.format("Request generated error: %s:%n  Request: %s %s",
                message,
                request.getMethod().getName(),
                request.getResourceRef().toString());
    }

    /**
     * The error message for unknown users.
     *
     * @param user A short string describing the problem.
     * @return A string describing the problem.
     */
    public String undefinedUser(String user) {
        return String.format("Undefined user %s:%n  Request: %s %s",
                user,
                request.getMethod().getName(),
                request.getResourceRef().toString());
    }

    /**
     * The error message for requests involving projects not owned by the specified user.
     *
     * @param user    The user.
     * @param project The project.
     * @return A string describing the problem.
     */
    public String cannotViewProject(String user, String project) {
        return String.format("User %s not allowed to view project %s:%n  Request: %s %s",
                user, project,
                request.getMethod().getName(),
                request.getResourceRef().toString());
    }

    /**
     * The error message for requests where the requesting user is not the owner.
     *
     * @param user    The user.
     * @param project The project
     * @return A string describing the problem.
     */
    public String notProjectOwner(String user, String project) {
        return String.format("Authorized user %s is not owner of project %s%n  Request: %s %s",
                user, project,
                request.getMethod().getName(),
                request.getResourceRef().toString());
    }


    /**
     * The error message for requests where a timestamp is not supplied or is not parsable.
     *
     * @param timestamp The bogus timestamp.
     * @return A string describing the problem.
     */
    public String badTimestamp(String timestamp) {
        return String.format("Bad timestamp %s:%n  Request: %s %s",
                timestamp,
                request.getMethod().getName(),
                request.getResourceRef().toString());
    }


    /**
     * The error message for requests involving projects not owned by the specified user.
     *
     * @param userEmail The user.
     * @param project   The project.
     * @return A string describing the problem.
     */
    public String undefinedProject(String userEmail, String project) {
        return String.format("Undefined project %s for user %s:%n  Request: %s %s",
                project, userEmail,
                request.getMethod().getName(),
                request.getResourceRef().toString());
    }

    /**
     * Creates and returns a new Restlet StringRepresentation built from xmlData.
     * The xmlData will be prefixed with a processing instruction indicating UTF-8 and version 1.0.
     *
     * @param xmlData The xml data as a string.
     * @return A StringRepresentation of that xmldata.
     */
    public static StringRepresentation getStringRepresentation(String xmlData) {
        return getStringRepresentation(xmlData, true);
    }

    /**
     * Creates and returns a new Restlet StringRepresentation built from xmlData.
     * The xmlData will be prefixed with a processing instruction indicating UTF-8 and version 1.0.
     *
     * @param xmlData The xml data as a string.
     * @param includeXmlDecl true if xml decl should be prepended
     * @return A StringRepresentation of that xmldata.
     */
    public static StringRepresentation getStringRepresentation(String xmlData, boolean includeXmlDecl) {
        StringBuilder builder = new StringBuilder(500);
        if (includeXmlDecl) {
            builder.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        }
        builder.append(xmlData);
        return new StringRepresentation(builder, MediaType.TEXT_XML, Language.ALL, CharacterSet.UTF_8);
    }

    /**
     * Helper function that removes any newline characters from the supplied string and
     * replaces them with a blank line.
     *
     * @param msg The msg whose newlines are to be removed.
     * @return The string without newlines.
     */
    public String removeNewLines(String msg) {
        return msg.replace(System.getProperty("line.separator"), " ");
    }

}
